package com.qqtech.qquan.circle.service;

import java.util.LinkedHashMap;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.qqtech.core.common.enums.YesNoEnum;
import com.qqtech.core.common.exception.BizzException;
import com.qqtech.core.common.util.StringUtil;
import com.qqtech.core.common.util.TimeUtil;
import com.qqtech.core.frame.dao.BaseDao;
import com.qqtech.core.frame.model.PageKit;
import com.qqtech.core.frame.model.PageOrder;
import com.qqtech.core.frame.service.BaseServiceImpl;
import com.qqtech.qquan.circle.dao.CircleBaseDao;
import com.qqtech.qquan.circle.dao.CircleInfoDao;
import com.qqtech.qquan.circle.dao.CircleMemberDao;
import com.qqtech.qquan.circle.enums.CircleAuditStatusEnum;
import com.qqtech.qquan.circle.enums.CircleFuncTypeDictEnum;
import com.qqtech.qquan.circle.enums.CircleMemberTypeDictEnum;
import com.qqtech.qquan.circle.enums.CircleZoneLevelDictEnum;
import com.qqtech.qquan.circle.model.CircleBase;
import com.qqtech.qquan.circle.model.CircleBaseVo;
import com.qqtech.qquan.circle.model.CircleMember;
import com.qqtech.qquan.circle.model.CircleMemberGradeVo;
import com.qqtech.qquan.circle.model.CircleMemberQuery;
import com.qqtech.qquan.circle.model.CircleMemberVo;
import com.qqtech.qquan.community.service.CommunityJoinService;
import com.qqtech.qquan.hi.service.HiCircleService;
import com.qqtech.qquan.im.enums.ImRetrunEnum;
import com.qqtech.qquan.im.service.ImGroupService;
import com.qqtech.qquan.user.service.UserBaseService;

@Service
public class CircleMemberServiceImpl extends BaseServiceImpl<CircleMember> implements CircleMemberService {
	public static final Logger log = LoggerFactory.getLogger(CircleMemberServiceImpl.class);

	@Resource
	private CircleMemberDao circleMemberDao;
	
	@Resource
	private CircleMemberGradeService circleMemberGradeService;
	
	@Resource
	private CircleInfoDao circleInfoDao;
	@Resource
	private CircleBaseDao circleBaseDao;
	@Resource
	private CircleBaseService circleBaseService;
	@Resource
	private ImGroupService imGroupService;
	@Resource
	private CommunityJoinService communityJoinService;

	@Resource
	private UserBaseService userBaseService;
	@Resource
	private CircleMemberLogService circleMemberLogService;
	
	@Resource
	private HiCircleService hiCircleService;
	
	@Override
	protected BaseDao<CircleMember> getBaseDao() {
		return circleMemberDao;
	}

	@Override
	public List<CircleMemberVo> queryCircleMembers(int circleId) {
		CircleMember cMember = new CircleMember();
		cMember.setCircleId(circleId);
		Pageable pageKit = new PageKit(1, Integer.MAX_VALUE, new PageOrder(Direction.ASC, "type"), new PageOrder(Direction.ASC, "id"));
		return circleMemberDao.queryList(cMember, pageKit);
	}
	
	@Override
	public List<CircleMemberVo> queryPartOfCircleMembers(int circleId,int queryCount) {
		CircleMember cMember = new CircleMember();
		cMember.setCircleId(circleId);
		Pageable pageKit = new PageKit(1, queryCount, new PageOrder(Direction.ASC, "id"));
		return circleMemberDao.queryList(cMember, pageKit);
	}
	@Override
	public List<Integer> queryMyCircleIds(CircleMemberQuery query) {
		return circleMemberDao.queryMyCircleIds(query);
	}

	@Override
	public boolean isCircleMember(Integer userId, Integer circleId) {
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setMemberId(userId);
		return circleMemberDao.queryCount(member) > 0;
	}

	@Override
	public boolean isCircleManager(Integer userId, Integer circleId) {
		CircleMember member = new CircleMember();
		member.setMemberId(userId);
		member.setCircleId(circleId);
		member.setType(CircleMemberTypeDictEnum.MANAGER.getCode());
		return circleMemberDao.queryCount(member) > 0;
	}

	@Override
	public int handleKickMember(Integer memberId, Integer circleId) throws BizzException {
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子或群聊id为空！");
		}
		if (memberId == null || memberId == 0) {
			throw new BizzException("成员id为空！");
		}
		CircleBaseVo circleVo = circleBaseService.getById(circleId);
		boolean isGroupChat = false;//是否群聊
		if(circleVo!=null){
			if(circleVo.isGroupChat()){
				isGroupChat = true;
			}
		}
		if (circleBaseService.isCircleCreator(memberId, circleId)) {
			if(isGroupChat){
				throw new BizzException("不能踢出该群主！");
			}else{
				throw new BizzException("不能踢出该圈主！");
			}
		}
		if (!isCircleMember(memberId, circleId)) {
			if(isGroupChat){
				throw new BizzException("该用户不是这群聊的成员！");
			}else{
				throw new BizzException("该用户不是这圈子的成员！");
			}
		}
		CircleBase circle = circleBaseService.getById(circleId);

		CircleMember removeMember = new CircleMember();
		removeMember.setCircleId(circleId);
		removeMember.setMemberId(memberId);
		int deleteRows = circleMemberDao.delete(removeMember);// 删除这个成员
		if (deleteRows == 1) {
			circleMemberLogService.logKillOutCircle(memberId, circleId);//添加【被踢出圈子】记录
			if (circle.getFuncType() != CircleFuncTypeDictEnum.TOPICONLY.getCode()) {
				imGroupService.deleteGroupMember(circleId, memberId);// IM删除群组成员（一个）
			}
			return circleInfoDao.reduceMemberCount(circleId, 1);// 成员数量-1
		}
		//TODO: 消息推送给 memberId
		return 0;
	}

	@Override
	public int handleQuitCircle(Integer userId, Integer circleId) throws BizzException {
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子或群聊id为空！");
		}
		CircleBaseVo circleVo = circleBaseService.getById(circleId);
		boolean isGroupChat = false;//是否群聊
		if(circleVo!=null){
			if(circleVo.isGroupChat()){
				isGroupChat = true;
			}
		}
		if (circleBaseService.isCircleCreator(userId, circleId)) {
			if(isGroupChat){
				throw new BizzException("您是群主,不能退出该群聊！");
			}else{
				throw new BizzException("您是圈主,不能退出该圈子！");
			}
		}
		if (!isCircleMember(userId, circleId)) {
			if(isGroupChat){
				throw new BizzException("您不是该群聊的成员！");
			}else{
				throw new BizzException("您不是该圈子的成员！");
			}
		}
		CircleBase circle = circleBaseService.getById(circleId);

		CircleMember removeMember = new CircleMember();
		removeMember.setCircleId(circleId);
		removeMember.setMemberId(userId);
		int deleteRows = circleMemberDao.delete(removeMember);// 删除这个成员
		if (deleteRows == 1) {
			circleMemberLogService.logQuitOutCircle(userId, circleId);//添加【退出圈子】记录
			if (circle.getFuncType() != CircleFuncTypeDictEnum.TOPICONLY.getCode()) {
				imGroupService.deleteGroupMember(circleId, userId);// IM删除群组成员（一个）
			}
			return circleInfoDao.reduceMemberCount(circleId, 1);// 成员数量-1
		} else {
			throw new BizzException("退出失败！");
		}
	}

	@Override
	public int handleJoinCircle(Integer userId, Integer circleId, boolean isMe2JoinCircle) throws BizzException {
		
		String callUser = "她/他";
		if(isMe2JoinCircle){
			callUser = "您";
		}
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子id为空！");
		}
		CircleBaseVo circleVo = circleBaseDao.getById(circleId);
		if (circleVo.getIsOfficial()) {
			throw new BizzException("不能加入官方圈子！");
		}
		if(circleVo.getAuditStatus()!=CircleAuditStatusEnum.AUDIT_PASS.getCode()){
			throw new BizzException("该圈子未审批量过,不能加入!");
		}
		if (isCircleMember(userId, circleId)) {
			throw new BizzException(callUser+"已是这个圈子的成员,不能重加入！");
		}
		if (circleVo.getZoneLevel() == CircleZoneLevelDictEnum.SINGLE_COMMUNITY.getCode()) {
			Integer communityId = circleVo.getCommunityId();
			if(communityId!=null){
				if (!communityJoinService.isJoinCommunity(circleVo.getCommunityId(), userId)) {
					throw new BizzException(callUser+"所属社区不在该圈子服务范围");
				}
			}
			
		}else if(circleVo.getZoneLevel() == CircleZoneLevelDictEnum.MULTI_COMMUNITY.getCode()){
			int joinCount = 0;
			if (communityJoinService.isJoinCommunity(circleVo.getCommunityId(), userId)) {
				//查询用户是否加入了该圈子原本的社区
				joinCount ++;
			}
			String extCommunityids = circleVo.getExtCommunityIds();
			if(StringUtil.isNotBlank(extCommunityids)){
				String[] communityIds = extCommunityids.split(";");
				for(String communityId:communityIds){
					if (communityJoinService.isJoinCommunity(Integer.parseInt(communityId), userId)) {
						//查询用户是否加入了该圈子扩展的社区
						joinCount ++;
					}
				}
			}
			if(joinCount<=0){
				throw new BizzException(callUser+"所属社区不在该圈子服务范围");
			}
		}
		boolean isAllNoActivity = circleBaseService.isKeepAllMemberNoActivity(circleId);//是否所有成员都不能发布活动
		boolean isAllNoVote = circleBaseService.isKeepAllMemberNoVote(circleId);//是否所有成员都不能发布投票
		
		CircleMember cMember = new CircleMember();
		cMember.setCircleId(circleId);
		cMember.setMemberId(userId);
		cMember.setType(CircleMemberTypeDictEnum.MEMBER.getCode());// 普通成员
		int insertRow = circleMemberDao.insert(cMember);
		if (insertRow > 0) {
			circleMemberLogService.logJoinCircle(userId, circleId);//添加【加入圈子】记录
			if(isAllNoActivity){
				circleBaseService.updateAllMemberCanAddActivity(circleId, YesNoEnum.NO);
			}
			if(isAllNoVote){
				circleBaseService.updateAllMemberCanAddVote(circleId, YesNoEnum.NO);
			}
			if (circleVo.getFuncType() != CircleFuncTypeDictEnum.TOPICONLY.getCode()) {
				int ret = imGroupService.addGroupMember(circleId, userId);// IM添加群组成员（一个）
				if(ret == ImRetrunEnum.FAIL.getCode()){
					imGroupService.addGroupMember(circleId, userId);//如果添加群聊成员失败，再调一次
				}
			}
			circleInfoDao.increaseMemberCount(circleId, 1);// 成员数量+1
			hiCircleService.join(userId, circleId);//荣誉系统--加入圈子
		}
		return insertRow;
	}
	
	@Override
	public int handleJoinGroupChat(Integer userId, Integer chatCircleId) throws BizzException {
		if (chatCircleId == null || chatCircleId == 0) {
			throw new BizzException("群聊id为空！");
		}
		if (isCircleMember(userId, chatCircleId)) {
			throw new BizzException("他/她已是这个群聊的成员,不能重加入！");
		}
		CircleMember cMember = new CircleMember();
		cMember.setCircleId(chatCircleId);
		cMember.setMemberId(userId);
		cMember.setType(CircleMemberTypeDictEnum.MEMBER.getCode());// 普通成员
		int insertRow = circleMemberDao.insert(cMember);
		if (insertRow > 0) {
			circleMemberLogService.logJoinCircle(userId, chatCircleId);//添加【加入圈子】记录
			int ret = imGroupService.addGroupMember(chatCircleId, userId);// IM添加群组成员（一个）
			if(ret == ImRetrunEnum.FAIL.getCode()){
				imGroupService.addGroupMember(chatCircleId, userId);//如果添加群聊成员失败，再调一次
			}
			return circleInfoDao.increaseMemberCount(chatCircleId, 1);// 成员数量+1
		}
		return 0;
	}

	@Override
	public List<Integer> queryMyOpenCircleIds(Integer userId) {
		return circleMemberDao.queryMyOpenCircleIds(userId);
	}

	@Override
	public int addCircleManager(Integer userId, Integer circleId) throws BizzException {
		CircleMemberVo cMemberVo = new CircleMemberVo();
		cMemberVo.setCircleId(circleId);
		cMemberVo.setMemberId(userId);
		cMemberVo = this.getCircleMember(userId, circleId);
		CircleBaseVo circleVo = circleBaseService.getById(circleId);
		boolean isGroupChat = false;//是否群聊
		if(circleVo!=null){
			if(circleVo.isGroupChat()){
				isGroupChat = true;
			}
		}
		if(cMemberVo==null){
			if(isGroupChat){
				throw new BizzException("该用户不是这群聊的成员！");
			}else{
				throw new BizzException("该用户不是这圈子的成员！");
			}
		}
		if (cMemberVo.getType() == CircleMemberTypeDictEnum.MANAGER.getCode()) {
			throw new BizzException("该成员已经是管理员！");
		}
		if (cMemberVo.getType() == CircleMemberTypeDictEnum.OWNER.getCode()) {
			if(isGroupChat){
				throw new BizzException("该成员群主！");
			}else{
				throw new BizzException("该成员是圈主！");
			}
		}
		if (cMemberVo.getId() != null) {
			CircleMember cMember4update = new CircleMember();
			cMember4update.setId(cMemberVo.getId());
			cMember4update.setType(CircleMemberTypeDictEnum.MANAGER.getCode());
			return circleMemberDao.updateById(cMember4update);
		}
		//TODO: 消息推送给 userId
		return 0;
	}

	@Override
	public int removeCircleManager(Integer userId, Integer circleId) throws BizzException {
		CircleMemberVo cMemberVo = new CircleMemberVo();
		cMemberVo = this.getCircleMember(userId, circleId);
		CircleBaseVo circleVo = circleBaseService.getById(circleId);
		boolean isGroupChat = false;//是否群聊
		if(circleVo!=null){
			if(circleVo.isGroupChat()){
				isGroupChat = true;
			}
		}
		if(cMemberVo==null){
			if(isGroupChat){
				throw new BizzException("该用户不是这群聊的成员！");
			}else{
				throw new BizzException("该用户不是这圈子的成员！");
			}
		}
		if (cMemberVo.getType() != CircleMemberTypeDictEnum.MANAGER.getCode()) {
			throw new BizzException("该成员还不是管理员！");
		}
		if (cMemberVo.getType() == CircleMemberTypeDictEnum.OWNER.getCode()) {
			throw new BizzException("该成员圈主！");
		}
		if (cMemberVo.getId() != null) {
			CircleMember cMember4update = new CircleMember();
			cMember4update.setId(cMemberVo.getId());
			cMember4update.setType(CircleMemberTypeDictEnum.MEMBER.getCode());
			return circleMemberDao.updateById(cMember4update);
		}
		//TODO: 消息推送给 userId
		return 0;
	}

	@Override
	public List<Integer> queryOurcircleIds(Integer userId, Integer userId2) {
		List<Integer> userCircles = queryMyOpenCircleIds(userId);
		if(null!=userCircles&&userCircles.size()>0){
			CircleMemberQuery circleMemberQuery=new CircleMemberQuery();
			circleMemberQuery.setMemberId(userId2);
			circleMemberQuery.setIsPrivate(YesNoEnum.NO.getCode());
			circleMemberQuery.setCircleIds(userCircles);
			return circleMemberDao.queryCircleIds(circleMemberQuery);
		}
		return Lists.newArrayList();
	}

	@Override
	public int setBlack(Integer memberId, Integer circleId, boolean isBlack) throws BizzException {
		if (circleId == null || circleId == 0) {
			throw new BizzException("圈子id为空！");
		}
		if (memberId == null || memberId == 0) {
			throw new BizzException("成员id为空！");
		}
		if (circleBaseService.isCircleCreator(memberId, circleId)) {
			throw new BizzException("该成员是圈主,不能屏蔽！");
		}
		
		CircleMemberVo cMemberVo = new CircleMemberVo();
		cMemberVo = this.getCircleMember(memberId, circleId);
		if(cMemberVo==null){
			throw new BizzException("该用户不是这圈子的成员！");
		}
		if(cMemberVo.isBlack() && isBlack){
			throw new BizzException("该用户已经被屏蔽,不能重复操作！");
		}
		if(!cMemberVo.isBlack() && !isBlack){
			throw new BizzException("该用户还没有被屏蔽,不能取消屏蔽！");
		}
		if(cMemberVo.getId()!=null){
			CircleMember updateMember = new CircleMember();
			updateMember.setId(cMemberVo.getId());
			updateMember.setIsBlack(isBlack? YesNoEnum.YES.getCode():YesNoEnum.NO.getCode());
			return circleMemberDao.updateById(updateMember);
		}
		return 0;
	}

	/**
	 * 这个方法只能用在成员的基础上
	 */
	@Override
	public boolean isBlack(Integer userId, Integer circleId) {
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setMemberId(userId);
		member.setIsBlack(YesNoEnum.YES.getCode());
		return circleMemberDao.queryCount(member) > 0;
	}

	@Override
	public int increaseSignCount(Integer circleId, Integer memberId) {
		return circleMemberDao.increaseSignCount(circleId, memberId, 1);
	}

	@Override
	public int increaseTopicCount(Integer circleId, Integer memberId) {
		return circleMemberDao.increaseTopicCount(circleId, memberId, 1);
	}

	@Override
	public int handleCanAddVote(Integer circleId, Integer memberId, YesNoEnum canAddVote) throws BizzException {
		CircleMemberVo memberVo = this.getCircleMember(memberId, circleId);
		if(memberVo==null){
			throw new BizzException("找不到该成员");
		}
		CircleMember member4update = new CircleMember();
		member4update.setId(memberVo.getId());
		member4update.setCanAddVote(canAddVote.getCode());
		return circleMemberDao.updateById(member4update);
		//TODO: 消息推送给 userId
	}

	@Override
	public int handleCanAddActivity(Integer circleId, Integer memberId, YesNoEnum canAddActivity) throws BizzException {
		CircleMemberVo memberVo = this.getCircleMember(memberId, circleId);
		if(memberVo==null){
			throw new BizzException("找不到该成员");
		}
		CircleMember member4update = new CircleMember();
		member4update.setId(memberVo.getId());
		member4update.setCanAddActivity(canAddActivity.getCode());
		return circleMemberDao.updateById(member4update);
		//TODO: 消息推送给 userId
	}

	@Override
	public boolean isCanAddVote2Circle(Integer userId, Integer circleId) {
		if(circleBaseService.isCircleCreator(userId, circleId)){
			return true;//圈主不受限
		}
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setMemberId(userId);
		member.setCanAddVote(YesNoEnum.YES.getCode());
		return circleMemberDao.queryCount(member)>0;
	}

	@Override
	public boolean isCanAddActivity2Circle(Integer userId, Integer circleId) {
		if(circleBaseService.isCircleCreator(userId, circleId)){
			return true;//圈主不受限
		}
		CircleMember member = new CircleMember();
		member.setCircleId(circleId);
		member.setMemberId(userId);
		member.setCanAddActivity(YesNoEnum.YES.getCode());
		return circleMemberDao.queryCount(member)>0;
	}

	@Override
	public CircleMemberVo getCircleMember(Integer userId, Integer circleId) {
		if(circleId==null || userId==null){
			return null;
		}
		CircleMember memberQ = new CircleMember();
		memberQ.setCircleId(circleId);
		memberQ.setMemberId(userId);
		List<CircleMemberVo> memberList= circleMemberDao.queryList(memberQ);
		if(memberList!=null && memberList.size()>0){
			return memberList.get(0);
		}else{
			return null;
		}
		
	}
	@Override
	public String getCircleMemberGradeName(Integer userId, Integer circleId) {
		if(circleBaseService.isCircleCreator(userId, circleId)){
			return "圈主";
		}
		if(isCircleManager(userId,circleId)){
			return "管理员";
		}
		CircleMemberVo memberVo = this.getCircleMember(userId, circleId);
		if(memberVo!=null){
			CircleMemberGradeVo memberGrade = circleMemberGradeService.getMemberGrade(circleId, memberVo.getGradeCode());
			return memberGrade==null? "" : memberGrade.getGradeName();
		}else{
			return "";
		}
		
		
	}

	@Override
	public List<Integer> queryCircleMemberIds(Integer circleId) {
		return circleMemberDao.queryCircleMemberIds(circleId);
	}

	@Override
	public List<CircleMemberVo> queryCircleFullMember(Integer circleId) {
		return circleMemberDao.queryCircleFullMember(circleId);
	}
	
	@Override
	public List<CircleMemberVo> queryPartOfCircleFullMember(Integer circleId) {
		return circleMemberDao.queryPartOfCircleFullMember(circleId);
	}
	
	@Override
	public LinkedHashMap<Integer, CircleMemberVo> getCircleFullMemberMap(Integer circleId) {
		LinkedHashMap<Integer, CircleMemberVo> map = new LinkedHashMap<Integer, CircleMemberVo>();
		List<CircleMemberVo> memberList = this.queryCircleFullMember(circleId);
		if(memberList!=null && memberList.size()>0){
			for(CircleMemberVo member:memberList){
				if (null == map.get(member.getMemberId())) {
					map.put(member.getMemberId(), member);
				}
			}
		}
		return map;
	}
	
	@Override
	public List<CircleMemberVo> queryCircleTopicCreators(Integer circleId) {
		return circleMemberDao.queryCircleTopicCreators(circleId);
	}
	
	@Override
	public LinkedHashMap<Integer, CircleMemberVo> getCircleTopicCreatorsMap(Integer circleId) {
		LinkedHashMap<Integer, CircleMemberVo> map = new LinkedHashMap<Integer, CircleMemberVo>();
		List<CircleMemberVo> memberList = this.queryCircleTopicCreators(circleId);
		if(memberList!=null && memberList.size()>0){
			for(CircleMemberVo member:memberList){
				if (null == map.get(member.getMemberId())) {
					map.put(member.getMemberId(), member);
				}
			}
		}
		return map;
	}
	
	@Override
	public List<CircleMemberVo> queryCircleManagers(int circleId) {
		CircleMember cMember = new CircleMember();
		cMember.setCircleId(circleId);
		cMember.setType(CircleMemberTypeDictEnum.MANAGER.getCode());//管理员
		Pageable pageKit = new PageKit(1, Integer.MAX_VALUE, new PageOrder(Direction.ASC, "id"));
		return circleMemberDao.queryList(cMember, pageKit);
	}
	
	@Override
	public int syncLastTopicTime (Integer memberId, Integer circleId) {
		CircleMember member = this.getCircleMember(memberId, circleId);
		if(member!=null){
			CircleMember member4Update = new CircleMember();
			member4Update.setId(member.getId());
			member4Update.setLastTopicAt(TimeUtil.now());
			return circleMemberDao.updateById(member4Update);
		}
		return 0;
	}

}